package com.Ghao.websocketDemo;

import com.Ghao.websocketDemo.entity.SocketMsg;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author Ghao
 * @date 2021/4/23 14:23
 */
@ServerEndpoint(value = "/websocket/{nickname}")
@Component
public class MyWebSocket {

    /**
     * 用来存放每个客户端对应的MyWebSocket对象
     *
     * @author Ghao
     * @date 2021/4/23 14:29
     * @param
     * @return
     */
    private static final CopyOnWriteArraySet<MyWebSocket> WEB_SOCKET_SET = new CopyOnWriteArraySet<>();

    private static Map<String, Session> map = new HashMap<>();

    /**
     * 用来保存某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    /**
      * 用户名
      */
    private String nickname;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("nickname") String nickname) {
        this.session = session;
        this.nickname = nickname;
        WEB_SOCKET_SET.add(this);
        map.put(session.getId(), session);
        System.out.println("用户"+ nickname +"加入聊天室，当前在线人数为：" + WEB_SOCKET_SET.size());
        this.session.getAsyncRemote().sendText("恭喜您连接上webSocket --> 频道号：" + session.getId()+ "当前在线人数为：" + WEB_SOCKET_SET.size());
    }

    /**
      *连接关闭调用的方法
      */
    @OnClose
    public void onClose(@PathParam("nickname") String nickname){
        WEB_SOCKET_SET.remove(this);
        System.out.println("用户" + nickname + "退出！当前在线人数为" + WEB_SOCKET_SET.size());
    }

    /**
      * 收到客户端消息后调用的方法
      */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("nickname") String nickname){
        System.out.println("来自用户" + nickname + "的消息：" + message);
        ObjectMapper objectMapper = new ObjectMapper();
        SocketMsg socketMsg;
        try{
            socketMsg = objectMapper.readValue(message, SocketMsg.class);
            if (1 == socketMsg.getType()){
                socketMsg.setFromUser(session.getId());
                Session fromSession = map.get(socketMsg.getFromUser());
                Session toSession = map.get(socketMsg.getToUser());
                if (null != toSession){
                    String toNickname = null;
                    Iterator<MyWebSocket> iterator = WEB_SOCKET_SET.iterator();
                    while (iterator.hasNext()){
                        MyWebSocket webSocket = iterator.next();
                        if (toSession == webSocket.session){
                            toNickname = webSocket.nickname;
                        }
                    }
                    fromSession.getAsyncRemote().sendText(this.nickname + " : " +socketMsg.getMsg() + "（发给" + toNickname + "悄悄话）");
                    toSession.getAsyncRemote().sendText(nickname + " : " + socketMsg.getMsg() + "（来自 " + nickname + "悄悄话）");
                }else {
                    fromSession.getAsyncRemote().sendText("系统消息：对方不在线或者您输入的频道号不存在");
                }
            }else {
                broadcast(socketMsg.getMsg(), nickname);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    /**
      *收到错误时调用
      */
    @OnError
    public void onError(Session session, Throwable throwable){
        System.out.println("发生了错误");
    }
    private void broadcast(String message, String nickname) {
        for (MyWebSocket item : WEB_SOCKET_SET){
            //异步发送消息
            item.session.getAsyncRemote().sendText(nickname + "：" + message);
        }
    }

}
